﻿using Basic.FlowCollect;
using Basic.FlowExtendService;
using Basic.FlowRemoteModel;
using Basic.FlowRemoteModel.FlowAudit.Model;
using Basic.FlowService.Interface;
using Basic.FlowService.Model.AuditLog;
using Basic.FlowService.Model.LogItem;
using Basic.FlowService.Model.Node;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;
using WeDonekRpc.Model;

namespace Basic.FlowService.lmpl
{
    internal class FlowAuditLogService : IFlowAuditLogService
    {
        private readonly IFlowAuditLogCollect _AuditLog;
        private readonly IEmpService _Emp;
        private readonly IFlowAuditItemLogCollect _LogItem;
        private readonly IFlowNodeCollect _Node;
        public FlowAuditLogService ( IFlowAuditLogCollect auditLog,
            IFlowAuditItemLogCollect item,
            IFlowNodeCollect node,
            IEmpService emp )
        {
            this._Node = node;
            this._LogItem = item;
            this._Emp = emp;
            this._AuditLog = auditLog;
        }

        public FlowLogItem[] GetLogItems ( long logId )
        {
            var items = this._LogItem.GetItems(logId, a => new
            {
                a.Id,
                a.NodeId,
                a.EmpId
            });
            long[] nodeId = items.ConvertAll(a => a.NodeId);
            Dictionary<long, string> node = this._Node.GetNames(nodeId);
            return items.ConvertAll(a => new FlowLogItem
            {
                Id = a.Id,
                NodeId = a.NodeId,
                EmpId = a.EmpId,
                NodeName = node.GetValueOrDefault(a.NodeId)
            });
        }

        public PagingResult<AuditLogItem> Query ( AuditLogQuery query, IBasicPage paging )
        {
            UserAuditLog[] logs = this._AuditLog.Query<UserAuditLog>(query, paging, out int count);
            if ( logs.IsNull() )
            {
                return new PagingResult<AuditLogItem>();
            }
            long[] logId = logs.Where(a => a.Status == FlowAuditLogStatus.进行中).Select(a => a.Id).ToArray();
            List<long> empId = new List<long>();
            logs.ForEach(a =>
            {
                empId.Add(a.CreateBy);
                if ( a.EndEmpId.HasValue )
                {
                    empId.Add(a.EndEmpId.Value);
                }
            });
            List<long> nodeId = new List<long>();
            LogItemDto[] items = null;
            if ( logId.Length > 0 )
            {
                items = this._LogItem.GetRunItems<LogItemDto>(logId);
                items.ForEach(c =>
                {
                    empId.Add(c.EmpId);
                    nodeId.Add(c.NodeId);
                });
            }
            Dictionary<long, string> empName = this._Emp.GetNames(empId.Distinct().ToArray());
            NodeBaseDto[] nodes = this._Node.Gets<NodeBaseDto>(nodeId.Distinct().ToArray());
            AuditLogItem[] dtos = logs.ConvertAll(a =>
            {
                AuditLogItem it = new AuditLogItem
                {
                    AuditStatus = a.AuditStatus,
                    CreateBy = a.CreateBy,
                    Status = a.Status,
                    CreateName = empName.GetValueOrDefault(a.CreateBy),
                    EndTime = a.EndTime,
                    CreateTime = a.CreateTime,
                    DocTitle = a.DocTitle,
                    Id = a.Id,
                    LinkPk = a.LinkPk,
                    LinkType = a.LinkType,
                    ProgressVal = a.ProgressVal,
                    EndEmpId = a.EndEmpId,
                    EndEmp = a.EndEmpId.HasValue ? empName.GetValueOrDefault(a.EndEmpId.Value) : null
                };
                if ( a.Status == FlowAuditLogStatus.进行中 )
                {
                    it.CurItem = items.Where(a => a.LogId == a.LogId).GroupBy(a => a.NodeId).Select(a =>
                    {
                        NodeBaseDto t = nodes.Find(c => c.Id == a.Key);
                        long[] empId = a.Select(c => c.EmpId).ToArray();
                        return new AuditCurItem
                        {
                            AuditType = t.AuditType,
                            EmpId = empId,
                            NodeId = t.Id,
                            NodeName = t.NodeName,
                            NodeType = t.NodeType,
                            EmpName = empId.Join(',', c => empName.GetValueOrDefault(c))
                        };
                    }).ToArray();
                }
                return it;
            });

            return new PagingResult<AuditLogItem>(dtos, count);
        }
    }
}
